package com.ruoyi.web.controller.system;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpClientResult;
import com.ruoyi.common.utils.http.HttpClientUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.WeChatUserInfo;
import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.IWeChatUserInfoService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 登录验证
 * 
 * @author ruoyi
 */
@RestController
@Component
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IWeChatUserInfoService weChatUserInfoService;

    @Value("${wechat.redirectUri}")
    private String redirectUri;

    @Value("${wechat.appId}")
    private String appId;

    @Value("${wechat.appSecret}")
    private String appSecret;


    private Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 后台登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/loginback")
    public AjaxResult loginback(@RequestBody LoginBody loginBody)
    {
        SysUser sysUser = userService.getUserByPhone(loginBody.getMobile());
        userService.checkUserAllowed(sysUser);
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 登录方法
     * 
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 手机号登录方法
     *
     * @param
     * @return 结果
     */
    @ApiOperation("手机号登录")
    @ApiImplicitParam(name = "loginBody", value = "登录信息", dataType = "LoginBody")
    @PostMapping("/sms/login")
    public AjaxResult smsLogin(@RequestBody LoginBody loginBody)
    {
        String mobile=loginBody.getMobile();
        String smsCode=loginBody.getSmsCode();
        String uuid=loginBody.getUuid();
        AjaxResult ajax = loginService.smsLogin(mobile, smsCode,
                uuid);
        return ajax;
    }

    /**
     * 微信授权登录
     */
    @ApiOperation("微信登录")
    @RequestMapping(value = "/wx/login", method = RequestMethod.GET)
    public void weLogin(HttpServletResponse response) throws Exception {
        //防止csrf攻击(跨站请求伪造攻击)
        String state = UUID.randomUUID().toString().replace("-", "");
        //通过redis缓存state 使用sessionID为key 30分钟后过期, 可配置
        redisCache.setCacheObject("wechat-open-state-123", state, 30, TimeUnit.MINUTES);
        String url = "https://open.weixin.qq.com/connect/qrconnect?" +"appid=" + appId +"&redirect_uri=" + URLEncoder.encode(redirectUri, "UTF-8") +
                     "&response_type=code" +"&scope=snsapi_login" +"&state=" +state +"#wechat_redirect";
        response.sendRedirect(url);
    }

    /**
     * 授权回调信息
     */
    @ApiOperation("微信回调")
    @RequestMapping(value = "/wx/openWxCallBack", method = RequestMethod.GET)
    public AjaxResult openWxCallBack(HttpServletRequest httpServletRequest) throws Exception {
        String code = httpServletRequest.getParameter("code");
        System.out.println(code);
        String state = httpServletRequest.getParameter("state");
        System.out.println(state);
        String url = null;
        //判断state的合法性
        String stateStr = redisCache.getCacheObject("wechat-open-state-123");
        System.out.println(stateStr);
        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(stateStr) || !state.equals(stateStr)) {
            logger.info("非法参数，请重新登陆");
        }else if(StringUtils.isNotEmpty(stateStr)){
            redisCache.deleteObject("wechat-open-state-123");
        }
        url = "https://api.weixin.qq.com/sns/oauth2/access_token?" + "appid=" + appId + "&secret=" + appSecret  + "&code=" + code + "&grant_type=authorization_code";
        HttpClientResult wechatAccessToken = HttpClientUtils.doGet(url);
        String content = wechatAccessToken.getContent();
        JSONObject wxJson = JSONObject.parseObject(content);
        System.out.println(wxJson);
        logger.info("返回参数信息：" + wxJson);
        if (wxJson.get("errcode") != null) {
            logger.info("获取accessToken失败");
        }
        String accessToken = (String) wxJson.get("access_token");
        String openid = (String) wxJson.get("openid");
        String unionid = (String) wxJson.get("unionid");
        String refreshToken = (String) wxJson.get("refresh_token");
        String chickUrl="https://api.weixin.qq.com/sns/auth?access_token="+accessToken+"&openid="  + appId;
        HttpClientResult chickuserInfo = HttpClientUtils.doGet(chickUrl);
        //由于access_token拥有较短的有效期，当access_token超时后，可以使用refresh_token进行刷新，refresh_token有效期为30天，当refresh_token失效之后，需要用户重新授权
        //如果发送错误，就有可能是access_token过期了 errcode 的值是 0 那么就是没有问题，access_token没有过期,不等于0就是过期，那么我们要去刷新access_token
//        if(!"0".equals(JSON.parseObject(chickuserInfo.getContent()).get("errcode"))){
//            //第三步刷新access_token(刷新access_token接口)
//            String refreshTokenUrl="https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=wx1c5811f42b237e36"+"&grant_type=refresh_token&refresh_token="+refreshToken;
//            HttpClientResult refreshInfo = HttpClientUtils.doGet(chickUrl);
//
//            accessToken=(String) JSON.parseObject(refreshInfo.getContent()).get("access_token");
//        }
        if (StringUtils.isEmpty(accessToken) || StringUtils.isEmpty(openid) || StringUtils.isEmpty(unionid)) {
            logger.info("获取accessToken失败");
        }
        WeChatUserInfo weChatUserInfo = weChatUserInfoService.selectWxUserById(unionid);//数据库信息
        if (weChatUserInfo == null) {
            WeChatUserInfo weChatUserInfoReal = getUserInfoByAccessToken(accessToken);
//            System.out.println(weChatUserInfoReal);
//            weChatUserInfoService.insertWxUser(weChatUserInfoReal);
            return AjaxResult.success(weChatUserInfoReal);
        }
        return AjaxResult.success(weChatUserInfo);
    }

    private WeChatUserInfo getUserInfoByAccessToken(String accessToken) throws Exception{
        if (StringUtils.isEmpty(accessToken)) {
            return null; //"accessToken为空";
        }
        String get_userInfo_url = null;
        get_userInfo_url = "https://api.weixin.qq.com/sns/userinfo?" +
                "access_token=" +
                accessToken +
                "&openid="  + appId;
        HttpClientResult userInfo_result = HttpClientUtils.doGet(get_userInfo_url);
        if (!userInfo_result.equals("errcode")) {
            WeChatUserInfo weChatUserInfo = JSON.parseObject(userInfo_result.getContent(), WeChatUserInfo.class);
            return weChatUserInfo; //"获取用户信息失败"
        }
            return null;
    }

    /**
     * 获取用户信息
     * 
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        SysUser user = loginUser.getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }

    /**
     * 获取路由信息
     * 
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        // 用户信息
        SysUser user = loginUser.getUser();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(user.getUserId());
        return AjaxResult.success(menuService.buildMenus(menus));
    }
}
